home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / AMScen_0_9.lha / AMScen / monsters.m < prev    next >
Text File  |  1995-01-21  |  14KB  |  496 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1995 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * monsters.m - define some monster classes and monsters.
  9.  */
  10.  
  11. private tp_monsters CreateTable().
  12. use tp_monsters
  13.  
  14. /* a move routine for a simple random moving monster */
  15.  
  16. /*
  17.  * RandomMove - used for dumb monsters which just wander around.
  18.  */
  19.  
  20. define t_monsters proc public RandomMove()void:
  21.     thing me;
  22.     int n;
  23.     action a;
  24.  
  25.     me := Me();
  26.     if MonsterStillMoving(me, nil) then
  27.     a := me@p_mSpecialAction;
  28.     if a ~= nil then
  29.         if not call(a, bool)() then
  30.         /* something special - give it a new lease on life */
  31.         me@p_mMovesUntilVanish := RANDOM_MONSTER_LIFE + 1;
  32.         MonsterReschedule(me);
  33.         fi;
  34.     else
  35.         DoMonsterMove(me);
  36.         MonsterReschedule(me);
  37.     fi;
  38.     fi;
  39. corp;
  40.  
  41. /* set up monsters which will pick up and use stuff */
  42.  
  43. define t_monsters proc public MonsterPickUp()void:
  44.     list thing lt;
  45.     int count, i, carryCount, n;
  46.     thing here, me, th, old;
  47.  
  48.     me := Me();
  49.     here := Here();
  50.     lt := here@p_rContents;
  51.     count := Count(lt);
  52.     carryCount := Count(me@p_pCarrying);
  53.     i := 0;
  54.     while i < count and carryCount < MAX_CARRY do
  55.     th := lt[i];
  56.     if not th@p_oInvisible and not th@p_oNotGettable then
  57.         if DoGet(here, me, th) ~= continue then
  58.         /* something wrong - quit trying to get things */
  59.         i := count;
  60.         else
  61.         count := count - 1;
  62.         carryCount := carryCount + 1;
  63.         n := th@p_oArmourProt;
  64.         old := me@p_pArmour;
  65.         if old = nil and n ~= 0 or
  66.             old ~= nil and n < old@p_oArmourProt
  67.         then
  68.             SetIt(th);
  69.             ignore call(th@p_oWearChecker, status)();
  70.             /* make him live forever */
  71.             me@p_mMovesUntilVanish := FOREVER_LIFE;
  72.         else
  73.             n := th@p_oShieldProt;
  74.             old := me@p_pShield;
  75.             if old = nil and n ~= 0 or
  76.             old ~= nil and n < old@p_oShieldProt
  77.             then
  78.             SetIt(th);
  79.             ignore call(th@p_oUseChecker, status)();
  80.             me@p_mMovesUntilVanish := FOREVER_LIFE;
  81.             else
  82.             n := th@p_oDamage;
  83.             old := me@p_pWeapon;
  84.             if old = nil and n ~= 0 or
  85.                 old ~= nil and n > old@p_oDamage
  86.             then
  87.                 SetIt(th);
  88.                 ignore call(th@p_oWieldChecker, status)();
  89.                 me@p_mMovesUntilVanish := FOREVER_LIFE;
  90.             fi;
  91.             fi;
  92.         fi;
  93.         fi;
  94.     else
  95.         i := i + 1;
  96.     fi;
  97.     od;
  98. corp;
  99.  
  100. /* set up trackers */
  101.  
  102. define t_monsters p_mTrackerPath CreateIntListProp().
  103. define t_monsters p_pTrackerList CreateThingListProp().
  104.  
  105. /*
  106.  * TrackerDieNotify - called when a player with trackers dies. Return 'true'
  107.  *    to indicate that we want to be removed from the notify list.
  108.  */
  109.  
  110. define t_monsters proc TrackerDieNotify(thing thePlayer)bool:
  111.     list thing trackers;
  112.     int count;
  113.     thing tracker;
  114.     list int path;
  115.  
  116.     trackers := thePlayer@p_pTrackerList;
  117.     count := Count(trackers);
  118.     while count ~= 0 do
  119.     count := count - 1;
  120.     tracker := trackers[count];
  121.     tracker -- p_mTrackerPath;
  122.     RemTail(trackers);
  123.     od;
  124.     true
  125. corp
  126.  
  127. /*
  128.  * TrackerChecker - a player leave checker that records the direction on all
  129.  *    following trackers
  130.  */
  131.  
  132. define t_monsters proc TrackerChecker(int dir)status:
  133.     list thing lt;
  134.     int count, n, dirCount;
  135.     thing me, tracker;
  136.     list int li;
  137.  
  138.     me := Me();
  139.     lt := me@p_pTrackerList;
  140.     if lt = nil then
  141.     DelPlayerLeaveChecker(me, TrackerChecker);
  142.     DelElement(me@p_pDieNotifyList, TrackerDieNotify);
  143.     else
  144.     count := Count(lt);
  145.     if count ~= 0 then
  146.         n := 0;
  147.         while n ~= count do
  148.         tracker := lt[n];
  149.         if tracker@p_mExpired then
  150.             DelElement(lt, tracker);
  151.             DestroyMachine(tracker);
  152.             count := count - 1;
  153.         else
  154.             li := tracker@p_mTrackerPath;
  155.             if li = nil then
  156.             li := CreateIntList();
  157.             tracker@p_mTrackerPath := li;
  158.             dirCount := 0;
  159.             else
  160.             dirCount := Count(li);
  161.             fi;
  162.             if dirCount ~= 0 and li[dirCount - 1] = DirBack(dir) then
  163.             /* two directions cancel out */
  164.             RemTail(li);
  165.             else
  166.             AddTail(li, dir);
  167.             fi;
  168.             n := n + 1;
  169.         fi;
  170.         od;
  171.     fi;
  172.     if count = 0 then
  173.         me -- p_pTrackerList;
  174.         DelPlayerLeaveChecker(me, TrackerChecker);
  175.         DelElement(me@p_pDieNotifyList, TrackerDieNotify);
  176.     fi;
  177.     fi;
  178.     continue
  179. corp;
  180.  
  181. /*
  182.  * TrackerDie - a die action for trackers, as called by MonsterStillMoving
  183.  */
  184.  
  185. define t_monsters proc TrackerDie(thing me)void:
  186.     list thing lt;
  187.     thing target;
  188.  
  189.     target := me@p_pCurrentTarget;
  190.     if target ~= nil then
  191.     lt := target@p_pTrackerList;
  192.     if lt ~= nil and FindElement(lt, me) ~= -1 then
  193.         DelElement(lt, me);
  194.         if Count(lt) = 0 then
  195.         target -- p_pTrackerList;
  196.         DelPlayerLeaveChecker(target, TrackerChecker);
  197.         DelElement(target@p_pDieNotifyList, TrackerDieNotify);
  198.         fi;
  199.     fi;
  200.     fi;
  201. corp;
  202.  
  203. /*
  204.  * TrackerKill - routine to do extra stuff when a tracker is killed.
  205.  *    NOTE: this should be attached to each model of a tracker.
  206.  */
  207.  
  208. define t_monsters proc TrackerKill(thing me)bool:
  209.  
  210.     TrackerDie(me);
  211.     KillMonster(me);
  212.     DestroyMachine(me);
  213.     false
  214. corp;
  215.  
  216. /*
  217.  * TrackerInit - extra init stuff for a tracker.
  218.  */
  219.  
  220. define t_monsters proc TrackerInit()void:
  221.     thing me, thePlayer;
  222.     list thing trackers;
  223.  
  224.     me := Me();
  225.     if me@p_mKillAction = nil then
  226.     /* should be on the model, but if not... */
  227.     me@p_mKillAction := TrackerKill;
  228.     fi;
  229.     MonsterInit();
  230.     thePlayer := me@p_pCurrentTarget;
  231.     trackers := thePlayer@p_pTrackerList;
  232.     if trackers = nil then
  233.     trackers := CreateThingList();
  234.     thePlayer@p_pTrackerList := trackers;
  235.     AddPlayerLeaveChecker(thePlayer, TrackerChecker, false);
  236.     AddTail(thePlayer@p_pDieNotifyList, TrackerDieNotify);
  237.     fi;
  238.     AddTail(trackers, me);
  239. corp;
  240.  
  241. /*
  242.  * TrackerMove - a tracker moves a single step, hopefully on the path
  243.  *    following the target.
  244.  */
  245.  
  246. define t_monsters proc TrackerMove()void:
  247.     thing me, target, here;
  248.     list int li;
  249.     int dir, count;
  250.     bool followed;
  251.  
  252.     me := Me();
  253.     here := Here();
  254.     li := me@p_mTrackerPath;
  255.     if li = nil then
  256.     count := 0;
  257.     else
  258.     count := Count(li);
  259.     fi;
  260.     target := me@p_pCurrentTarget;
  261.     if AgentLocation(target) = here then
  262.     ignore MonsterHitPlayer(me, target, here);
  263.     me@p_mTrackerPath := CreateIntList();
  264.     MonsterReschedule(me);
  265.     else
  266.     followed := false;
  267.     if count ~= 0 then
  268.         dir := li[0];
  269.         RemHead(li);
  270.         if MonsterMove(me, dir) then
  271.         followed := true;
  272.         else
  273.         /* rats! can't follow */
  274.         me -- p_mTrackerPath;
  275.         fi;
  276.     fi;
  277.     if not followed then
  278.         /* where did he go, where did he go? */
  279.         if not MonsterMove(me, Random(12)) then
  280.         if MonsterStillMoving(me, TrackerDie) then
  281.             MonsterAction(me);
  282.             MonsterReschedule(me);
  283.         fi;
  284.         else
  285.         MonsterReschedule(me);
  286.         fi;
  287.     else
  288.         MonsterReschedule(me);
  289.     fi;
  290.     fi;
  291. corp;
  292.  
  293. /* define some "standard" monsters.
  294.    Note: numerics: hitpoints, speed, protection, accuracy, damage, gold */
  295.  
  296. define t_monsters m_rat CreateMonsterModel("rat",
  297.     "The rat is of average size, and, like most rats, is quite filthy.",
  298.     MonsterInit, RandomMove,
  299.     2, 6, 9, 5, 2, 0).
  300. AddModelAction(m_rat, "runs around").
  301. AddModelAction(m_rat, "chitters").
  302. AddModelAction(m_rat, "squeals").
  303.  
  304. define t_monsters m_snake CreateMonsterModel("snake",
  305.     "The snake isn't poisonous, but bites pretty well. It has no "
  306.     "distinguishing markings.",
  307.     MonsterInit, RandomMove,
  308.     4, 8, 9, 5, 2, 0).
  309. AddModelAction(m_snake, "slithers around").
  310. AddModelAction(m_snake, "hisses").
  311. AddModelAction(m_snake, "coils and uncoils").
  312.  
  313. define t_monsters m_dog CreateMonsterModel("dog;wild", "",
  314.     MonsterInit, RandomMove,
  315.     6, 5, 9, 5, 3, 0).
  316. m_dog@p_mBlocker := true.
  317. AddModelAction(m_dog, "runs around").
  318. AddModelAction(m_dog, "barks").
  319. AddModelAction(m_dog, "growls").
  320. AddModelAction(m_dog, "snarls").
  321.  
  322. define t_monsters m_gremlin CreateMonsterModel("gremlin;nasty",
  323.     "The gremlin, like all of its kind, is quite dirty. It also comes "
  324.     "equipped with sharp teeth and claws.",
  325.     MonsterInit, RandomMove,
  326.     5, 5, 9, 5, 3, 15).
  327. AddModelAction(m_gremlin, "runs in circles around you").
  328. AddModelAction(m_gremlin, "shrieks loudly").
  329. AddModelAction(m_gremlin, "curses").
  330. AddModelAction(m_gremlin, "picks its nose").
  331. AddModelAction(m_gremlin, "thumbs its nose").
  332. AddModelAction(m_gremlin, "spits at you").
  333.  
  334. /* and now some bigger stuff for forests, etc. */
  335.  
  336. define t_monsters m_wolf CreateMonsterModel("wolf", "",
  337.     MonsterInit, RandomMove,
  338.     10, 5, 9, 7, 6, 0).
  339. m_wolf@p_mBlocker := true.
  340. AddModelAction(m_wolf, "runs around").
  341. AddModelAction(m_wolf, "snarls").
  342. AddModelAction(m_wolf, "howls").
  343.  
  344. define t_monsters m_troll CreateMonsterModel("troll", "",
  345.     MonsterInit, RandomMove,
  346.     13, 4, 8, 6, 6, 40).
  347. m_troll@p_mBlocker := true.
  348. AddModelAction(m_troll, "lumbers around").
  349. AddModelAction(m_troll, "bellows").
  350. AddModelAction(m_troll, "raises its fists and roars").
  351.  
  352. define t_monsters m_blackBear CreateMonsterModel("bear;black", "",
  353.     MonsterInit, RandomMove,
  354.     15, 5, 8, 6, 6, 0).
  355. m_blackBear@p_mBlocker := true.
  356. AddModelAction(m_blackBear, "lumbers around").
  357. AddModelAction(m_blackBear, "roars").
  358. AddModelAction(m_blackBear, "stands upright and waves its paws").
  359.  
  360. define t_monsters m_deer CreateMonsterModel("deer;mule", "",
  361.     MonsterInit, RandomMove,
  362.     8, 7, 9, 0, 0, 0).
  363. AddModelAction(m_deer, "leaps around").
  364. AddModelAction(m_deer, "screams silently").
  365. AddModelAction(m_deer, "snorts").
  366. define tp_monsters proc deerArrivalCheck(thing theDeer, theArrival)void:
  367.  
  368.     if IsAncestor(theArrival, m_wolf) or IsAncestor(theArrival, m_troll) then
  369.     RunAway(theDeer);
  370.     fi;
  371. corp;
  372. m_deer@p_mArriveAction := deerArrivalCheck.
  373. define tp_monsters proc deerCreationCheck(thing theDeer, theNew)void:
  374.  
  375.     if IsAncestor(theNew, m_wolf) or IsAncestor(theNew, m_troll) then
  376.     RunAway(theDeer);
  377.     fi;
  378. corp;
  379. m_deer@p_mCreateAction := deerCreationCheck.
  380. define tp_monsters proc deerArrivedCheck()void:
  381.     thing here;
  382.  
  383.     here := Here();
  384.     if FindAgentAsDescendant(here, m_wolf) ~= nil or
  385.     FindAgentAsDescendant(here, m_troll) ~= nil
  386.     then
  387.     ignore RunAwaySoon();
  388.     fi;
  389. corp;
  390. m_deer@p_mArrivedAction := deerArrivedCheck.
  391.  
  392. define t_monsters m_moose CreateMonsterModel("moose", "",
  393.     MonsterInit, RandomMove,
  394.     18, 4, 7, 6, 4, 0).
  395. m_moose@p_mBlocker := true.
  396. AddModelAction(m_moose, "wades around").
  397. AddModelAction(m_moose, "snorts").
  398. AddModelAction(m_moose, "bellows").
  399.  
  400. /* larger stuff for the sewers */
  401.  
  402. define t_monsters m_largeRat CreateMonsterModel("rat;large",
  403.     "The rat is of above average size and is quite filthy.",
  404.     MonsterInit, RandomMove,
  405.     4, 6, 9, 5, 4, 0).
  406. AddModelAction(m_largeRat, "runs around").
  407. AddModelAction(m_largeRat, "chitters loudly").
  408. AddModelAction(m_largeRat, "squeals loudly").
  409.  
  410. define t_monsters m_largeSnake CreateMonsterModel("snake;large",
  411.     "The snake isn't poisonous, but bites pretty well. It has pretty "
  412.     "red and yellow stripes running down its length.",
  413.     MonsterInit, RandomMove,
  414.     8, 8, 9, 5, 4, 0).
  415. AddModelAction(m_largeSnake, "slithers around").
  416. AddModelAction(m_largeSnake, "hisses").
  417. AddModelAction(m_largeSnake, "coils and uncoils").
  418.  
  419. define t_monsters m_goblin CreateMonsterModel("goblin",
  420.     "The goblin is a small, humanoid creature with pale skin, large eyes, "
  421.     "protruding ears, and sharp teeth. It walks in a perpetual crouch but "
  422.     "is nonetheless quite fast on its feet.",
  423.     MonsterInit, RandomMove,
  424.     10, 8, 9, 6, 5, 30).
  425. m_goblin@p_mBlocker := true.
  426. AddModelAction(m_goblin, "slouches around").
  427. AddModelAction(m_goblin, "gibbers").
  428. AddModelAction(m_goblin, "drools").
  429. AddModelAction(m_goblin, "howls").
  430. m_goblin@p_mAfterMoveAction := MonsterPickUp.
  431.  
  432. define t_monsters m_hugeRat CreateMonsterModel("rat;huge",
  433.     "The rat is quite large, but not totally filthy.",
  434.     MonsterInit, RandomMove,
  435.     8, 6, 10, 5, 8, 0).
  436. m_hugeRat@p_mBlocker := true.
  437. AddModelAction(m_hugeRat, "runs around").
  438. AddModelAction(m_hugeRat, "chitters loudly").
  439. AddModelAction(m_hugeRat, "squeals loudly").
  440.  
  441. define t_monsters m_hugeSnake CreateMonsterModel("snake;huge",
  442.     "The snake isn't poisonous, but bites pretty well. It has a very striking "
  443.     "checkerboard pattern.",
  444.     MonsterInit, RandomMove,
  445.     16, 8, 10, 5, 8, 0).
  446. m_hugeSnake@p_mBlocker := true.
  447. AddModelAction(m_hugeSnake, "slithers around").
  448. AddModelAction(m_hugeSnake, "hisses").
  449. AddModelAction(m_hugeSnake, "coils and uncoils").
  450.  
  451. define t_monsters m_fighterGoblin CreateMonsterModel("goblin;fighter",
  452.     "The goblin is a small, humanoid creature with pale skin, large eyes, "
  453.     "protruding ears, and sharp teeth. It walks in a perpetual crouch but "
  454.     "is nonetheless quite fast on its feet.",
  455.     MonsterInit, RandomMove,
  456.     20, 8, 10, 6, 10, 50).
  457. m_fighterGoblin@p_mBlocker := true.
  458. AddModelAction(m_fighterGoblin, "slouches around").
  459. AddModelAction(m_fighterGoblin, "gibbers").
  460. AddModelAction(m_fighterGoblin, "drools").
  461. AddModelAction(m_fighterGoblin, "howls").
  462. m_fighterGoblin@p_mAfterMoveAction := MonsterPickUp.
  463.  
  464. define t_monsters m_hugeSpider CreateMonsterModel("spider;huge",
  465.     "The spider's body is almost as large as yours, and it's long legs give "
  466.     "it good mobility and a long reach.",
  467.     MonsterInit, RandomMove,
  468.     16, 12, 15, 8, 12, 0).
  469. m_hugeSpider@p_mBlocker := true.
  470. AddModelAction(m_hugeSpider, "dances around").
  471. AddModelAction(m_hugeSpider, "clashes its fangs").
  472. AddModelAction(m_hugeSpider, "drips saliva").
  473. AddModelAction(m_hugeSpider, "waves its front legs menacingly").
  474.  
  475. define t_monsters m_trackerSpider CreateMonsterModel("spider;tracker",
  476.     "The spider's body is almost as large as yours, and it's long legs give "
  477.     "it good mobility and a long reach.",
  478.     TrackerInit, TrackerMove,
  479.     16, 12, 15, 8, 12, 0).
  480. m_trackerSpider@p_mBlocker := true.
  481. m_trackerSpider@p_mKillAction := TrackerKill.
  482. AddModelAction(m_trackerSpider, "dances around").
  483. AddModelAction(m_trackerSpider, "clashes its fangs").
  484. AddModelAction(m_trackerSpider, "drips saliva").
  485. AddModelAction(m_trackerSpider, "waves its front legs menacingly").
  486.  
  487. define t_monsters m_largeTroll CreateMonsterModel("troll;large", "",
  488.     MonsterInit, RandomMove,
  489.     26, 4, 7, 6, 12, 80).
  490. m_troll@p_mBlocker := true.
  491. AddModelAction(m_troll, "lumbers around").
  492. AddModelAction(m_troll, "bellows").
  493. AddModelAction(m_troll, "raises its fists and roars").
  494.  
  495. unuse tp_monsters
  496.